#!/usr/bin/env python
# encoding: utf-8
#
# Copyright (c) 2008 Doug Hellmann All rights reserved.
#
"""
"""

__version__ = "$Id: admin.py 153 2009-10-31 20:19:15Z doug.hellmann $"

# Import system modules
import glob
import logging
import os
from cStringIO import StringIO

# Import third-party modules
from django import http
from django import template
from django.conf import settings
import django.contrib.admin.views.main as admin_views
from django.contrib.admin.views.decorators import staff_member_required
from django.contrib.auth.decorators import login_required, permission_required
from django.http import Http404, HttpResponse, HttpResponseRedirect
from django import newforms
from django.newforms.util import ErrorList
from django.shortcuts import render_to_response
from django.views.decorators.cache import never_cache

# Import local modules
from docket.vtr_loader import load_data_from_stream, ErrorKeeper
from docket.models import Case, MediaFile

# Module

logger = logging.getLogger('docket.admin')

@permission_required('docket.case.can_add', login_url="/admin/")
def upload_vtr(request):
    logger.debug('upload_vtr')
    template_args = {
        'title':'Load VTR Data',
        'existing':0,
        'new':0,
        'output':'',
        'errors':[],
        'num_errors':0,
        'filename':'',
        }
    if request.method == 'POST':
        try:
            vtr_data = request.FILES['vtr_data']
        except KeyError:
            # Use the default arguments
            pass
        else:
            logger.debug(vtr_data)
            
            # Save the file
            archive_name = os.path.join(settings.VTR_ARCHIVE_DIR, os.path.basename(vtr_data['filename']))
            logger.debug('archiving to %s', archive_name)
            f = open(archive_name, 'wt')
            try:
                f.write(vtr_data['content'])
            finally:
                f.close()
            
            # Load the data from the uploaded file
            stream = StringIO(vtr_data['content'])
            out_buffer = StringIO()
            errors = ErrorKeeper()
            counts = load_data_from_stream(stream, message_stream=out_buffer, errorcb=errors)
        
            # Massage the error text
            for e in errors.errors:            
                e['body'] = '\n'.join('%5d: %s' % (n+e['start'], l)
                                    for (n, l) in enumerate(e['lines']))
            
            template_args = {
                'title':'Load VTR Data',
                'existing':counts[0],
                'new':counts[1],
                'output':out_buffer.getvalue(),
                'errors':errors.errors,
                'num_errors':len(errors.errors),
                'filename':vtr_data['filename'],
                }

    return render_to_response('load_vtr.html', template_args)

from django.newforms.util import ValidationError
class CaseIdListField(newforms.CharField):
    
    def clean(self, value):
        "Validates max_length and min_length. Returns a Unicode object."
        logger = logging.getLogger(__name__ + '.CaseIdListField')
        logger.debug('validating "%s"', value)
        value = super(CaseIdListField, self).clean(value)
        case_id_strings = value.splitlines()
        cases = []
        errors = []
        for line in case_id_strings:
            logger.debug('checking line "%s"', line)
            try:
                year_s, num_s = line.strip().split('/')
                year = int(year_s)
                num = int(num_s)
            except ValueError:
                errors.append('Could not convert "%s" to a case id' % line)
                continue
            try:
                cases.append(Case.objects.get(year=year, num=num))
            except Exception, e:
                errors.append('Case %s: %s' % (line, str(e)))
        if errors:
            logger.debug('Errors with case ids: %s', errors)
            raise ValidationError(errors)
        return cases
    
class MediaFileUploadForm(newforms.Form):
    title = newforms.CharField(widget=newforms.TextInput(attrs={'size':100}))
    citation = newforms.CharField(widget=newforms.TextInput(attrs={'size':100}), 
                                  help_text="Source info for image",
                                  )
    image = newforms.ImageField()
    cases = CaseIdListField(widget=newforms.Textarea(attrs={'cols':20, 'rows':10}),
                               help_text="Enter case ids as YEAR/NUM one per line.",
                               required=False,
                               )

@permission_required('docket.mediafile.can_add', login_url="/admin/")
def add_mediafile(request):
    logging.debug('add_mediafile POST=%s FILES=%s', request.POST, request.FILES)
    
    if request.POST:
        form = MediaFileUploadForm(request.POST, request.FILES)
        if form.is_valid():
            
            logger.debug('form is valid')
            new_mediafile = MediaFile(title=form.cleaned_data['title'],
                                      citation=form.cleaned_data['citation'],
                                      )
            filename = form.cleaned_data['image'].filename
            file_contents = form.cleaned_data['image'].content
            new_mediafile.save_image_file(filename, file_contents)
            new_mediafile.save()
            
            # Add the relationships to the case
            for case in form.cleaned_data['cases']:
                logger.debug('Adding case "%s" to mediafile "%s"', case, new_mediafile)
                new_mediafile.cases.add(case)
                    
            if "_continue" in request.POST:
                post_url_continue='../%s/'
                request.user.message_set.create(message="New media file added.  You may edit it again below.")
                if "_popup" in request.POST:
                    post_url_continue += "?_popup=1"
                return HttpResponseRedirect(post_url_continue % new_mediafile.id)
            else:
                # Clear the form to present an empty page
                form = MediaFileUploadForm()
                
        else:
            logger.debug('Form has errors: %s', form.errors)
            try:
                form.data['image'] = form.cleaned_data['image'].filename
            except (KeyError, AttributeError):
                pass
        
    else:
        form = MediaFileUploadForm()
    
        
    template_args = dict(
        form=form,
        first_form_field_id='id_title',
        opts=MediaFile._meta,
        )
    return render_to_response('add_mediafile.html', template_args)


class MediaFileChangeForm(newforms.Form):
    title = newforms.CharField(widget=newforms.TextInput(attrs={'size':100}))
    citation = newforms.CharField(widget=newforms.TextInput(attrs={'size':100}), 
                                  help_text="Source info for image",
                                  )
    cases = CaseIdListField(widget=newforms.Textarea(attrs={'cols':20, 'rows':10}),
                               help_text="Enter case ids as YEAR/NUM one per line.",
                               required=False,
                               )
    image = newforms.ImageField(required=False)

@permission_required('docket.mediafile.can_change', login_url="/admin/")
def change_mediafile(request, id):
    logger.debug('change_mediafile(%s) POST=%s FILES=%s', id, request.POST, request.FILES)
    
    if request.POST and "_saveasnew" in request.POST:
        return add_mediafile(request)
    
    existing_mediafile = MediaFile.objects.get(id=int(id))
    
    if request.POST:
        form = MediaFileChangeForm(request.POST, request.FILES)
        if form.is_valid():
            logger.debug('form is valid')
            
            # Update the simple values.
            existing_mediafile.title = form.cleaned_data['title']
            existing_mediafile.citation = form.cleaned_data['citation']
            existing_mediafile.save()
            
            # Update the cases related to the mediafile
            for c in existing_mediafile.cases.all():
                existing_mediafile.cases.remove(c)
            for c in form.cleaned_data['cases']:
                existing_mediafile.cases.add(c)
            
            # If the user provided a new image, replace any existing
            # versions of images with the new content.
            uploaded_image = form.cleaned_data['image']
            if uploaded_image:
                existing_filename = existing_mediafile.get_image_filename()                
                filename = uploaded_image.filename
                logger.debug('replacing file "%s" with "%s"', existing_mediafile.image, filename)
                file_contents = uploaded_image.content
                existing_mediafile.save_image_file(filename, file_contents)
                # Remove the original image and any resized versions
                pattern = '%s*x*%s' % os.path.splitext(existing_filename)
                remove = [ existing_filename ] + glob.glob(pattern)
                for f in remove:
                    logger.debug('removing "%s"', f)
                    try:
                        os.unlink(f)
                    except Exception, e:
                        logger.error('Could not remove "%s": %s', f, e)

    else:
        form = MediaFileChangeForm(initial={'title':existing_mediafile.title,
                                            'citation':existing_mediafile.citation,
                                            'image':existing_mediafile.image,
                                            'cases':'\n'.join(str(c) for c in existing_mediafile.cases.all()),
                                           },
                                    )

    template_args = dict(
        form=form,
        first_form_field_id='id_title',
        opts=MediaFile._meta,
        add=False,
        change=True,
        is_popup=False,
        has_delete_permission=True,
        has_change_permission=True,
        image_url=existing_mediafile.get_image_url(),
        )
    return render_to_response('change_mediafile.html', template_args)
            
    
    # if request.POST:
    #     form = MediaFileUploadForm(request.POST, request.FILES)
    #     if form.is_valid():
    #         
    #         logger.debug('form is valid')
    #         new_mediafile = MediaFile(title=form.cleaned_data['title'],
    #                                   citation=form.cleaned_data['citation'],
    #                                   )
    #         filename = form.cleaned_data['image'].filename
    #         file_contents = form.cleaned_data['image'].content
    #         new_mediafile.save_image_file(filename, file_contents)
    #         new_mediafile.save()
    #         
    #         # Add the relationships to the case
    #         for case in form.cleaned_data['cases']:
    #             logger.debug('Adding case "%s" to mediafile "%s"', case, new_mediafile)
    #             new_mediafile.cases.add(case)
    #                 
    #         if "_continue" in request.POST:
    #             post_url_continue='../%s/'
    #             request.user.message_set.create(message="New media file added.  You may edit it again below.")
    #             if "_popup" in request.POST:
    #                 post_url_continue += "?_popup=1"
    #             return HttpResponseRedirect(post_url_continue % new_mediafile.id)
    #         else:
    #             # Clear the form to present an empty page
    #             form = MediaFileUploadForm()
    #             
    #     else:
    #         logger.debug('Form has errors: %s', form.errors)
    #         try:
    #             form.data['image'] = form.cleaned_data['image'].filename
    #         except (KeyError, AttributeError):
    #             pass
    #     
    # else:
    #     form = MediaFileUploadForm()
    
        
    # template_args = dict(
    #     form=form,
    #     first_form_field_id='id_title',
    #     opts=MediaFile._meta,
    #     )
    # return render_to_response('add_mediafile.html', template_args)
